package com.ttxz.common.crash

import android.content.Context
import android.os.Looper
import android.widget.Toast
import com.hjq.toast.ToastUtils
import com.ttxz.common.base.utils.AppViewManager
import com.ttxz.common.utils.log.LogUtil
import java.io.PrintWriter
import java.io.StringWriter
import java.lang.Exception

/**
 * 简要说明
 *
 * @author ttxz
 * @date 2022/6/11 11:25
 */
class MyCrashHandler : Thread.UncaughtExceptionHandler {
    /**
     * 系统默认的UncaughtException处理类
     */
    private var mDefaultHandler: Thread.UncaughtExceptionHandler? = null
    private var mContext: Context? = null
    private var mCrashListener: MyCrashListener? = null
    fun init(context: Context?, crashListener: MyCrashListener?) {
        mContext = context
        //获取系统默认的UncaughtException处理器
        mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler()
        //设置该MyCrashHandler为程序的默认处理器
        Thread.setDefaultUncaughtExceptionHandler(this)
        mCrashListener = crashListener
    }

    override fun uncaughtException(t: Thread, e: Throwable) {
        e.printStackTrace()
        if (!handleExample(e) && mDefaultHandler != null) {
            // 如果用户没有处理则让系统默认的异常处理器来处理 目的是判断异常是否已经被处理
            mDefaultHandler!!.uncaughtException(t, e)
        } else {
            try { //Sleep 来让线程停止一会是为了显示Toast信息给用户，然后Kill程序
                Thread.sleep(4000)
            } catch (e1: InterruptedException) {
                e1.printStackTrace()
                LogUtil.e(e1, "[MyCrashHandler],uncaughtException: ")
            } catch (e2: Exception) {
                LogUtil.e(e2, "[MyCrashHandler],uncaughtException: ")
            }

            // 如果不关闭程序,会导致程序无法启动,需要完全结束进程才能重新启动
            restartApp()
        }
    }

    /**
     * 自定义错误处理,收集错误信息 将异常信息保存 发送错误报告等操作均在此完成.
     *
     * @param ex
     * @return true:如果处理了该异常信息;否则返回false.
     */
    private fun handleExample(ex: Throwable?): Boolean {
        // 如果已经处理过这个Exception,则让系统处理器进行后续关闭处理
        if (ex == null) {
            return false
        }
        object : Thread() {
            override fun run() {
                super.run()
                // Toast 显示需要出现在一个线程的消息队列中
                Looper.prepare()
                Toast.makeText(mContext, "很抱歉，程序出现异常，即将退出重启", Toast.LENGTH_LONG).show()
                ToastUtils.show("很抱歉，程序出现异常，即将退出")
                Looper.loop()
            }
        }.start()
        //将异常记录到本地的文件中
        try {
            if (mCrashListener != null) {
                mCrashListener!!.onCrash(throwableTOString(ex), ex)
            }
        } catch (e: Exception) {
        }
        return true
    }

    private fun throwableTOString(ex: Throwable): String {
        val sw = StringWriter()
        val pw = PrintWriter(sw)
        ex.printStackTrace(pw)
        return sw.toString()
    }

    /**
     * 重启应用
     */
    private fun restartApp() {
        // 重启应用
        mContext!!.startActivity(mContext!!.packageManager.getLaunchIntentForPackage(mContext!!.packageName))
        AppViewManager.exit()
    }
}